import api from "@/api/api";
import { ISendConfig, TMethod } from "./request";

interface TDecoratorOptions extends Omit<ISendConfig, "data" | "method"> {}

interface IXjwDecorator {
  [keyName: string]: (
    options: TDecoratorOptions
  ) => (
    tag: any,
    protoName: string,
    describe: PropertyDescriptor
  ) => PropertyDescriptor;
}

export interface ICommit {
  (fetchData: Pick<ISendConfig, "data">): Promise<any>;
  //   (fetchData: Partial<ISendConfig>): Promise<any>;
}

function baseFetch(
  this: any,
  arg: any[],
  options: TDecoratorOptions,
  method: ISendConfig["method"]
): void {
  // Pick<ISendConfig, "data">
  const commit: ICommit = (fetchData) => {
    return api.request({
      ...options,
      ...fetchData,
      method,
    });
  };
  this.value(...arg, commit);
}

const xjwDecorator: IXjwDecorator = {};

const xjwMethods: Array<TMethod> = ["POST", "GET", "DELETE", "PUT"];
xjwMethods.forEach((key) => {
  xjwDecorator[key] = (options: TDecoratorOptions) => {
    return function (
      tag: any,
      protoName: string,
      describe: PropertyDescriptor
    ) {
      return {
        ...describe,
        value(...arg: any[]) {
          baseFetch.apply(describe, [
            arg,
            options,
            key as ISendConfig["method"],
          ]);
        },
      };
    };
  };
});

export const Post = xjwDecorator["POST"];
export const Get = xjwDecorator["GET"];
export const Delete = xjwDecorator["DELETE"];
export const Put = xjwDecorator["PUT"];
